from ..toolchain import Toolchain
from .. import task 
from ..logging import loginfo


def esc(fn):
    return '"%s"' % (fn,)

class CToolchain(Toolchain):
    @classmethod
    @Toolchain.outputext("i")
    def preprocess(cls, infile, output, params):
        """
        c_include_path (list of strings)
        c_defines (list of strings)
        c_pedantic (bool)
        c_warn_all (bool)
        c_warn_none (bool)
        c_warn_as_error (bool)
        
        c_options (list of strings)
        """
        args = ["-x", "c-header", "-E", "-o", esc(output)]
        if params.c_include_path:
            for pth in params.c_include_path:
                args.append("-I%s" % (esc(pth),))
        if params.c_defines:
            for d in params.c_defines:
                args.append("-D%s" % (d,))
        if params.c_warn_none:
            args.append("-w")
        elif params.c_warn_all:
            args.append("-Wall")
        if params.c_pedantic:
            args.append("-pedantic")
        if params.c_warn_as_error:
            args.append("-Werror")
        if params.c_options:
            args.extend(params.c_options)
        args.append(esc(infile))
        task.add("gcc", args)
        open(output, "w").close()
    
    @classmethod
    @Toolchain.outputext("o")
    def compile(cls, infile, output, params):
        """
        c_include_path (list of strings)
        c_defines (list of strings)
        c_optimize (bool)
        c_debug (bool)
        c_ansi (bool)
        c_standard (string)
        c_no_builtins (bool)
        c_signed_char (bool)
        c_inline (bool)
        c_warn_all (bool)
        c_warn_none (bool)
        c_pedantic (bool)
        c_warn_as_error (bool)
        
        c_options (list of strings)
        """
        args = ["-x", "c", "-c", "-o", esc(output)]
        if params.c_include_path:
            for pth in params.c_include_path:
                args.append("-I%s" % (esc(pth),))
        if params.c_optimize:
            args.append("-O3")
        if params.c_debug:
            args.append("-g")
        if params.c_ansi:
            args.append("-ansi")
        if params.c_standard:
            args.append("-std=%s" % (params.c_standard,))
        if params.c_warn_none:
            args.append("-w")
        elif params.c_warn_all:
            args.append("-Wall")
        if params.c_pedantic:
            args.append("-pedantic")
        if params.c_warn_as_error:
            args.append("-Werror")
        if params.c_defines:
            for d in params.c_defines:
                args.append("-D%s" % (d,))
        if params.c_signed_char:
            args.append("-fsigned-char")
        if params.c_inline:
            args.append("-fgnu89-inline")
        if params.c_options:
            args.extend(params.c_options)
        args.append(esc(infile))
        task.add("gcc", args)
        open(output, "w").close()
    
    @classmethod
    @Toolchain.outputext(None)
    def executable(cls, infiles, output, params):
        """
        linker_strip (bool)
        linker_no_crt (bool)
        linker_static_crt (bool)
        linker_shared_crt (bool)
        linker_libs (list of strings)
        
        linker_options (list of strings)
        """
        args = ["-o", esc(output)]
        if params.linker_strip:
            args.append("-s")
        if params.linker_no_crt:
            args.append("-nostdlib")
        if params.linker_static_crt:
            args.append("-static-libgcc")
        if params.linker_shared_crt:
            args.append("-shared-libgcc")
        if params.linker_libs:
            for l in params.linker_libs:
                args.append("-l%s" % (l,))
        if params.linker_options:
            args.extend(params.linker_options)
        args.extend(esc(fn) for fn in infiles)
        task.add("gcc", args)
        open(output, "w").close()
    
    @classmethod
    @Toolchain.outputext("so")
    def dynlib(cls, infiles, output, params):
        """
        linker_strip (bool)
        linker_no_crt (bool)
        linker_static_crt (bool)
        linker_shared_crt (bool)
        linker_static (bool)
        linker_shared (bool)
        linker_libs (list of strings)
        
        linker_options (list of strings)
        """
        args = ["-o", esc(output)]
        if params.linker_strip:
            args.append("-s")
        if params.linker_no_crt:
            args.append("-nostdlib")
        if params.linker_static_crt:
            args.append("-static-libgcc")
        if params.linker_shared_crt:
            args.append("-shared-libgcc")
        if params.linker_static:
            args.append("-static")
        if params.linker_shared:
            args.append("-shared")
        if params.linker_libs:
            for l in params.linker_libs:
                args.append("-l%s" % (l,))
        if params.linker_options:
            args.extend(params.linker_options)
        args.extend(esc(fn) for fn in infiles)
        task.add("gcc", args)
        open(output, "w").close()
    
    @classmethod
    @Toolchain.outputext("a")
    def library(cls, infiles, output, params):
        """no params"""
        args = ["crs", esc(output)]
        args.extend(esc(fn) for fn in infiles)
        task.add("ar", args)
        open(output, "w").close()


class CppToolchain(CToolchain):
    @classmethod
    @Toolchain.outputext("o")
    def compile(cls, infile, output, params):
        raise NotImplementedError


class AsmToolchain(Toolchain):
    pass

class AdaToolchain(Toolchain):
    pass

class FortranToolchain(Toolchain):
    pass
















